-- Spyro gem basket thinker by Tatsuru

local gems = spyro.gems
local spyroadded

// Input: Number of gems to spawn
// Output: A table with the sequence of gem types to spawn
local function GemPayout(num)
	local loot = {}
	
	for i = MT_SPYRO_MAGENTAGEM, MT_SPYRO_REDGEM, -1
		local value = gems[i].value
		
		if num < value continue end
		
		local int = num / value
		
		for j = 1, int
			table.insert(loot, i)
		end
			
		num = $ - value*int
	end
	
	return loot
end

// Make baskets targetable by Fang or homing attackers.
addHook("MapThingSpawn", function(mo, mapt)
	mo.flags2 = $ | MF2_INVERTAIMABLE
	
	if not mapt.angle
		P_RemoveMobj(mo)
		return
	end
	
	mo.loot = GemPayout(mapt.angle)
end, MT_SPYRO_BASKET)

// Collision and damage handling
addHook("MobjCollide", function(basket, toucher)
	if not toucher.player return end
	if toucher.player.bot == 1 return end
	
	local vpos = toucher.momz > 0 and toucher.momz or 0
	local vneg = toucher.momz < 0 and toucher.momz or 0
	
	if not HeightCheck(toucher.z + vneg, toucher.z + toucher.height + vpos, basket.z, basket.z + basket.height)
		return
	end
		
	if P_PlayerCanDamage(toucher.player, basket)
		--local hangle = R_PointToAngle2(toucher.x, toucher.y, basket.x, basket.y)
		local vangle = R_PointToAngle2(FixedHypot(basket.x, basket.y), basket.z, FixedHypot(toucher.x, toucher.y), toucher.z)
		
		if toucher.player.panim != PA_DASH
			P_SetObjectMomZ(toucher, 8*sin(vangle), false) 
			--P_InstaThrust(toucher, hangle, 8*abs(cos(vangle)))
		end
		
		S_StartSound(basket, sfx_bskbrk)
		P_DamageMobj(basket, toucher, toucher, 1, 0)
	end
end, MT_SPYRO_BASKET)

// Fake the destruction of the basket.
// It will keep existing for as long as there are gems to spawn
addHook("MobjDeath", function(mo)
	mo.flags = $ & ~MF_SOLID
	--mo.flags = $ | MF_NOCLIPHEIGHT
	mo.counter = 24

	P_SpawnMobjFromMobj(mo, 0, 0, 4*FRACUNIT, MT_TNTDUST)
	
	return true
end, MT_SPYRO_BASKET)

// Hack that actually spawns the gems
addHook("MobjThinker", function(mo)
	if mo.health return end
	
	if mo.frame < 10
		if (leveltime % 2)
			mo.frame = $ + 1
		end
	else
		mo.state = S_INVISIBLE
	end
	
	if not #mo.loot return end
	
	local am = #mo.loot
	
	mo.sfxcount = $ or 0
	
	if (leveltime % 8) return end
	
	local loot = P_SpawnMobjFromMobj(mo, 0, 0, 30*FRACUNIT, table.remove(mo.loot, 1))
	local angle = FixedAngle(P_RandomKey(360)*FRACUNIT)
	local sfx = sfx_gemlt1 + mo.sfxcount
	
	loot.airborne = true
	loot.momx = 2 * cos(angle)
	loot.momy = 2 * sin(angle)
	loot.momz = 8*FRACUNIT
	
	loot.basket = mo.spawnpoint
	
	if not (am == 1 and not mo.sfxcount)
		S_StartSound(mo, sfx)
	end
	
	if mo.sfxcount < 6
		mo.sfxcount = $ + 1
	end
end, MT_SPYRO_BASKET)

// Spyro compatibility?
addHook("ThinkFrame", do
	if spyroadded return end
	
	for skin in skins.iterate
		if skin.name == "spyro"
		--enemies/objects that can be flamed
			rawset(_G, "flammableEnemies", {MT_PLAYER, MT_BLUECRAWLA, MT_REDCRAWLA, MT_GFZFISH, MT_REDBUZZ, MT_GOLDBUZZ, MT_JETTBOMBER, MT_JETTGUNNER, MT_CRAWLACOMMANDER, MT_SKIM, MT_POPUPTURRET, MT_SNAILER, MT_VULTURE, MT_POINTY, MT_ROBOHOOD, MT_EGGGUARD, MT_GSNAPPER, MT_MINUS, MT_UNIDUS, MT_PTERABYTE, MT_DRAGONBOMBER, MT_TNTBARREL, MT_PENGUINATOR, MT_POPHAT, MT_CACOLANTERN, MT_HANGSTER, MT_HIVEELEMENTAL, MT_BUMBLEBORE, MT_METALSONIC_BATTLE, MT_CANARIVORE, MT_GOOMBA, MT_BLUEGOOMBA, MT_SPYRO_BASKET})

		--enemies/objects that can be charged into
			rawset(_G, "chargeableEnemies", {MT_PLAYER, MT_BLUECRAWLA, MT_REDCRAWLA, MT_GFZFISH, MT_JETTBOMBER, MT_JETTGUNNER, MT_SKIM, MT_POPUPTURRET, MT_SPINCUSHION, MT_CRUSHSTACEAN, MT_BANPYURA, MT_JETJAW, MT_VULTURE, MT_POINTY, MT_FACESTABBER, MT_EGGGUARD, MT_SPRINGSHELL, MT_YELLOWSHELL, MT_UNIDUS, MT_PYREFLY, MT_PTERABYTE, MT_DRAGONBOMBER, MT_TNTBARREL, MT_PENGUINATOR, MT_POPHAT, MT_SPINBOBERT, MT_CACOLANTERN, MT_HANGSTER, MT_HIVEELEMENTAL, MT_BUMBLEBORE, MT_BUGGLE, MT_FANG, MT_CANARIVORE, MT_GOOMBA, MT_SPYRO_BASKET})
			
			spyroadded = true
		end
	end
end)

addHook("NetVars", function(net)
	spyroadded = net($)
end)